博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
票务小程序源码_使用AdonisJs构建支持票务应用程序-第2部分
阅读量:2509 次
发布时间:2019-05-11

本文共 31675 字,大约阅读时间需要 105 分钟。

票务小程序源码

This is the concluding part of Build A Support Ticket Application With AdonisJs. In part 1, we setup the application, built the authentication system for users to signup, login, and logout. We created the ticket and category model as well as their migrations and also defined their relationships. Lastly, we created our first ticket and sent the ticket information mail. In case you missed it, you should check out because we will be continuing from where we stopped.

这是使用AdonisJs构建支持票务应用程序的结尾部分。 在第1部分中,我们设置了应用程序,构建了用于用户注册,登录和注销的身份验证系统。 我们创建了票证和类别模型及其迁移,还定义了它们之间的关系。 最后,我们创建了第一张票证并发送了票证信息邮件。 万一您错过了它,您应该检查“ ,因为我们将从停止的地方继续。

In this part, we'll give users a way to see all the tickets they have created and also ability to view a particular ticket. We'll also cover commenting on a ticket and mark ticket as closed. Finally, we'll restrict access to the application to only authenticated users.

在这一部分中,我们将为用户提供一种查看他们创建的所有票证的能力,以及查看特定票证的能力。 我们还将介绍对票证的评论并将票证标记为已关闭。 最后,我们将只允许经过身份验证的用户访问应用程序。

( )

We start off by allowing our users to see a list of all the tickets they have created and from there they can go on to view a particular ticket. Add the code below to app/Http/Controllers/TicketsController.js:

首先,允许用户查看他们创建的所有票证的列表,然后从那里继续查看特定的票证。 将以下代码添加到app/Http/Controllers/TicketsController.js

// app/Http/Controllers/TicketsController.js// remember to add these to the top of fileconst Mail = use('Mail')const Validator = use('Validator')const Ticket = use('App/Model/Ticket')const RandomString = use('randomstring')const Category = use('App/Model/Category')/*** Display all tickets by a user.*/* userTickets(request, response) {
// Get all the tickets created by the currently authenticated user const tickets = yield Ticket.query().where('user_id', request.currentUser.id).fetch() // Get all categories const categories = yield Category.all() yield response.sendView('tickets.user_tickets', {
tickets: tickets.toJSON(), categories: categories.toJSON() })}

We are getting the tickets created by the currently authenticated user by passing request.currentUser.id to the where(), where we also get all the categories. The tickets together with the categories are passed to a view file which we'll create shortly. Before creating the view file, let's create the route that will handle displaying all tickets created by a user. Add the line below to app/Http/routes.js:

我们通过将request.currentUser.id传递给where()来获取当前已认证用户创建的票证,在那里我们还可以获取所有类别。 票证和类别一起传递到一个视图文件,我们将在不久后创建它。 在创建视图文件之前,让我们创建将用于显示用户创建的所有票证的路由。 app/Http/routes.js添加到app/Http/routes.js

// app/Http/routes.jsRoute.get('my_tickets', 'TicketsController.userTickets')

With the route created, let's go on and create the view. Create a new view file named user_tickets.njk within the resources/views/tickets directory and paste the code below to it:

创建路线后,让我们继续创建视图。 在resources/views/tickets目录中创建一个名为user_tickets.njk的新视图文件,并将以下代码粘贴到其中:

{% extends 'layouts.master' %}{% block title %} My Tickets {% endblock %}{% block content %}
My Tickets
{% if tickets.length == 0 %}

You have not created any tickets.

{% else %}
{% for ticket in tickets %}
{% endfor %}
Category Title Status Last Updated
{% for category in categories %} {% if category.id == ticket.category_id %} { { category.name }} {% endif %} {% endfor %} #{ { ticket.ticket_id }} - { { ticket.title }} {% if ticket.status == 'Open' %} { { ticket.status }} {% else %} { { ticket.status }} {% endif %} { { ticket.updated_at }}
{% endif %}
{% endblock %}

First, we check if there are tickets and then display them within a table. For the ticket category, we check if the ticket category_id is equal to the category id then display the name of the category.

首先,我们检查是否有票证,然后将其显示在表格中。 对于票证类别,我们检查票证category_id是否等于类别id然后显示类别的名称。

Now if you visit the route /my_tickets you should see a page listing the tickets that have been created my the currently authenticated user like the image below:

现在,如果您访问/my_tickets路线,您应该会看到一个页面,其中列出了由当前身份验证的用户创建的票证,如下图所示:

( )

Now that users can see a list of all the tickets they have created, wouldn't it be nice if they could view a particular ticket? Of course, it will.

现在,用户可以看到他们创建的所有票证的列表,如果他们可以查看特定的票证,那不是很好吗? 当然可以。

Let's tackle that. We want the user to be able to access a particular ticket by this route tickets/ticket_id. Okay, let's create the route in app/Http/routes.js:

让我们解决这个问题。 我们希望用户能够通过此路线tickets/ticket_id访问特定票证。 好的,让我们在app/Http/routes.js创建路由:

// app/Http/routes.jsRoute.get('tickets/:ticket_id', 'TicketsController.show')

As you can see, we pass a parameter :ticket_id (which will be the ID of a specific ticket) along with the route. When the user hits that route, the show(), which we are yet to create, will be triggered.

如您所见,我们传递了:ticket_id参数(将是特定票证的ID)以及路线。 当用户点击该路线时,将触发我们尚未创建的show()

Before we create the show(), let's define User to Ticket relationship.

在创建show() ,让我们定义用户与票证的关系。

( )

A Ticket can belong to a User, while a User can have many Tickets. This is a one to many relationship which we'll use Lucid to setup. Open the app/Model/User.js model and paste the code below into it:

一个票证可以属于一个用户,而一个用户可以拥有多个票证。 这是一对多的关系,我们将使用Lucid进行设置。 打开app/Model/User.js模型并将以下代码粘贴到其中:

// app/Model/User.js/*** A user can have many tickets*/tickets() {
return this.hasMany('App/Model/Ticket')}

Now let's edit the app/Model/Ticket.js model in the same manner to add the inverse relationship:

现在,让我们以相同的方式编辑app/Model/Ticket.js模型,以添加逆关系:

// app/Model/Ticket.js/*** A ticket belongs to a user*/user() {
return this.belongsTo('App/Model/User')}

Now add this code below to app/Http/Controllers/TicketsController.js:

现在,将以下代码添加到app/Http/Controllers/TicketsController.js

// app/Http/Controllers/TicketsController.js/*** Display a specified ticket.*/* show(request, response) {
// Get the ticket with the user that created it const ticket = yield Ticket.query() .where('ticket_id', request.param('ticket_id')) .with('user') .firstOrFail() // Get the ticket category const category = yield ticket.category().fetch() yield response.sendView('tickets.show', {
ticket: ticket.toJSON(), category: category.toJSON() })}

We get the ticket (with the ticket_id passed from the route using request.param('ticket_id')) along with the user that created it (using the relationship defined above). Remember from Part 1 where we define our Ticket to Category relationship, so we can get the category which the ticket belongs to using ticket.category().fetch(). And finally, we pass the ticket and category to a view file.

我们获得票证(使用request.param('ticket_id')从路线传递票证request.param('ticket_id') )以及创建request.param('ticket_id')的用户(使用上面定义的关系)。 请记住,在第1部分中,我们定义了票证与类别的关系,因此我们可以使用ticket.category().fetch()获得票证所属的类别。 最后,我们将票证和类别传递到视图文件。

Create a view file in the resources/views/tickets directory with the name show.njk and paste the code below into it:

resources/views/tickets目录中创建一个名为show.njk的视图文件,并将以下代码粘贴到其中:

{% extends 'layouts.master' %}{% block title %}{
{ ticket.title }}{% endblock %}{% block content %}
#{
{ ticket.ticket_id }} - {
{ ticket.title }}
{% include 'includes.status' %} {% include 'includes.errors' %}

{ { ticket.message }}

Categry: { { category.name }}

{% if ticket.status == 'Open' %} Status: { { ticket.status }} {% else %} Status: { { ticket.status }} {% endif %}

Created on: { { ticket.created_at }}


{
{ form.open({ url: '/comment', method: 'POST', class: 'form' }) }} {
{ csrfField }} {
{ form.hidden('ticket_id', ticket.id) }}
{ { form.textarea('comment', null, { class: 'form-control', rows: 10 }) }}
{ { form.button('Submit', null, { class: 'btn btn-primary' }) }}
{
{ form.close() }}
{% endblock %}

You should get something like the image below when you click on the link to a particular ticket.

当您单击特定票证的链接时,您应该会看到类似下图的内容。

If you noticed, there is a text box which will allow the user to reply/comment on the ticket. Don't worry, we'll get to it shortly. We'll be updating the resources/views/tickets/show.njk too to display the comments on the ticket.

如果您注意到,会有一个文本框,允许用户在票证上进行回复/评论。 不用担心,我们会尽快处理。 我们resources/views/tickets/show.njk更新resources/views/tickets/show.njk以在票证上显示评论。

( )

Now let's allow the user to comment on a ticket. But first, we need a place to store the comments. Create a Comment model and a migration file with the command below:

现在,让用户对故障单发表评论。 但是首先,我们需要一个地方来存储评论。 使用以下命令创建Comment模型和迁移文件:

./ace make:model Comment --migration

Open the migration file just created and update with the code below:

打开刚刚创建的迁移文件,并使用以下代码进行更新:

// database/migrations/...create_comment_table.js// comments table migration showing only the up() schemas with our modificationsthis.create('comments', (table) => {
table.increments() table.integer('ticket_id').unsigned() table.integer('user_id').unsigned() table.text('comment') table.timestamps()})

The schema is pretty straightforward. Run the migration:

该模式非常简单。 运行迁移:

./ace migration:run

( )

A Comment can belong to a Ticket, while a Ticket can have many Comments. This is a one to many relationship which we'll use Lucid to setup. Open the app/Model/Comment.js model and paste the code below into it:

注释可以属于故障单,而故障单可以具有许多注释。 这是一对多的关系,我们将使用Lucid进行设置。 打开app/Model/Comment.js模型并将以下代码粘贴到其中:

// app/Model/Comment.js/*** A comment belongs to a particular ticket*/ticket() {
return this.belongsTo('App/Model/Ticket')}

Now let's edit the app/Model/Ticket.js model in the same manner to add the inverse relationship:

现在,让我们以相同的方式编辑app/Model/Ticket.js模型,以添加逆关系:

// app/Model/Ticket.js/*** A ticket can have many comments*/comments() {
return this.hasMany('App/Model/Comment')}

( )

A Comment can belong to a User, while a User can have many Comments. This is a one to many relationship which we'll Lucid to setup. Open the app/Model/Comment.js model and paste the code below into it:

一个注释可以属于一个用户,而一个用户可以具有多个注释。 这是我们将要建立的一对多关系。 打开app/Model/Comment.js模型并将以下代码粘贴到其中:

// app/Model/Comment.js/*** A comment belongs to a user*/user() {
return this.belongsTo('App/Model/User')}

Now let's edit the app/Model/User.js model in the same manner to add the inverse relationship:

现在让我们以相同的方式编辑app/Model/User.js模型,以添加逆关系:

// app/Model/User.js/*** A user can have many comments*/comments() {
return this.hasMany('App/Model/Comment')}

( )

We need to create a new HTTP request controller that will handle all comments specific logics.

我们需要创建一个新的HTTP请求控制器,该控制器将处理所有注释特定的逻辑。

./ace make:controller Comments

This will create app/Http/Controllers/CommentsController.js. The CommentsController will have only one method called postComment().

这将创建app/Http/Controllers/CommentsController.jsCommentsController将只有一个称为postComment()方法。

// app/Http/Controllers/CommentsController.js// remember to add these to the top of fileconst Mail = use('Mail')const Validator = use('Validator')const Comment = use('App/Model/Comment')/*** Persist comment and mail user*/* postComment(request, response) {
// Get the currently authenticated user const user = request.currentUser // validate form input const validation = yield Validator.validateAll(request.all(), {
comment: 'required' }) // show error messages upon validation fail if (validation.fails()) {
yield request .withAll() .andWith({
errors: validation.messages() }) .flash() return response.redirect('back') } // persist comment to database const comment = yield Comment.create({
ticket_id: request.input('ticket_id'), user_id: user.id, comment: request.input('comment'), }) // Get the ticket the comment was made on const commentTicket = yield comment.ticket().fetch() // Get the user that created the ticket that was just commentted on const commentUser = yield commentTicket.user().fetch() // send mail if the user commenting is not the ticket owner if (commentUser.id != user.id) {
yield Mail.send('emails.ticket_comments', {
commentUser, user, commentTicket, comment }, (message) => {
message.to(commentUser.email, commentUser.username) message.from('support@adonissupport.dev') message.subject(`RE: ${
commentTicket.title} (Ticket ID: ${
commentTicket.ticket_id})`) }) } yield request.with({
status: 'Your comment has been submitted.' }).flash() response.redirect('back')}

What the postComment() does is simple; make sure the comment box is filled, store a comment in the comments table with the ticket_id, user_id and the actual comment. Then send an email, if the user commenting is not the ticket owner (that is, if the comment was made by an admin, an email will be sent to the ticket owner). And finally, display a status message.

postComment()作用很简单; 确保已填充注释框,并将注释与ticket_iduser_id和实际注释一起存储在comments表中。 然后,如果用户评论不是票证所有者,则发送电子邮件(即,如果评论是由管理员进行的,则电子邮件将发送给票证所有者)。 最后,显示状态消息。

You will notice that I used the relationships defined above extensively. Let me further explain the code snippet.

您会注意到,我广泛使用了上面定义的关系。 让我进一步解释代码片段。

// Get the ticket the comment was made onconst commentTicket = yield comment.ticket().fetch()// Get the user that created the ticket that was just commentted onconst commentUser = yield commentTicket.user().fetch()// send mail if the user commenting is not the ticket ownerif (commentUser.id != user.id) {
yield Mail.send('emails.ticket_comments', {
commentUser, user, commentTicket, comment }, (message) => {
message.to(commentUser.email, commentUser.username) message.from('support@adonissupport.dev') message.subject(`RE: ${
commentTicket.title} (Ticket ID: ${
commentTicket.ticket_id})`) })}

We get the ticket the comment was made on, and then we get the user that created the ticket that was just commented on. Next, we check to see if the user ID of the ticket that was commented on is not equal to the currently authenticated user ID. If it is (that is, ticket owner made the comment) there is no point sending an email to the user since he/she is the one that made the comment. If it is not (that is, an admin made the comment) an email is sent to the ticket owner.

我们获得了对该评论进行评论的票证,然后我们获得了创建该评论的票证的用户。 接下来,我们检查被注释的票证的用户ID是否不等于当前经过身份验证的用户ID。 如果是(即,票证拥有者发表了评论),就没有必要向用户发送电子邮件,因为他/她是发表评论的人。 如果不是(即由管理员发表评论),则会将电子邮件发送给票证所有者。

( )

Let's take a closer look at the comment box included in the resources/views/tickets/show.njk:

让我们仔细看看resources/views/tickets/show.njk中包含的注释框:

{
{ form.open({ url: '/comment', method: 'POST', class: 'form' }) }} {
{ csrfField }} {
{ form.hidden('ticket_id', ticket.id) }}
{
{ form.textarea('comment', null, { class: 'form-control', rows: 10 }) }}
{
{ form.button('Submit', null, { class: 'btn btn-primary' }) }}
{
{ form.close() }}

The form will be sent as a POST request to the comment route which we are yet to create. Go on and add this to app/Http/routes.js:

该表格将作为POST请求发送到我们尚未创建的comment路线。 继续并将其添加到app/Http/routes.js

// app/Http/routes.jsRoute.post('comment', 'CommentsController.postComment')

Now you should be able to comment on a ticket but even after commenting, you won't see the comment yet because we haven't updated the show ticket view to display comments. First, we need to update the TicketsController.js's show() to also fetch comments and pass it to the view.

现在您应该可以对故障单发表评论了,但是即使发表评论,您也不会看到该评论,因为我们还没有更新显示故障单视图以显示评论。 首先,我们需要更新TicketsController.jsshow()来获取注释并将其传递给视图。

// app/Http/Controllers/TicketsController.js/*** Display a specified ticket.*/* show(request, response) {
// Get the ticket with the user that created it const ticket = yield Ticket.query() .where('ticket_id', request.param('ticket_id')) .with('user') .firstOrFail() // Get the comments that have been made on the ticket with user that made the comments const comments = yield ticket.comments().with('user').fetch() const category = yield ticket.category().fetch() yield response.sendView('tickets.show', {
ticket: ticket.toJSON(), comments: comments.toJSON(), category: category.toJSON() })}

Also update resources/views/tickets/show.njk, add the code below just after <hr> to do just that.

还要更新resources/views/tickets/show.njk ,在<hr>之后添加以下代码即可。

{% for comment in comments %}
{
{ comment.user.username }}
{
{ comment.created_at }}
{
{ comment.comment }}
{% endfor %}

When a comment is made on a ticket, we should get a screen similar to the image below:

当对票进行评论时,我们将获得类似于下图的屏幕:

( )

Let's take a closer look at the mail sending snippet from the postComment() in the CommentsController:

让我们仔细看一下CommentsController postComment()的邮件发送片段:

// app/Http/Controllers/CommentsController.jsyield Mail.send('emails.ticket_comments', {
commentUser, user, commentTicket, comment }, (message) => {
message.to(commentUser.email, commentUser.username) message.from('support@adonissupport.dev') message.subject(`RE: ${
commentTicket.title} (Ticket ID: ${
commentTicket.ticket_id})`)})

The Mail's send() accepts a path to a view file email/ticket_comments.njk, an object of data (commentUser, user, commentTicket, and comment) we want to pass to the view file and lastly a callback. The view file will be inside the emails directory and will be used to compose the mail we want to send. The message argument passed to the callback is an instance of message builder which is used to build the mail by specifying who we want to send the mail to, who is sending the mail and the subject of the mail.

邮件的send()接受视图文件email/ticket_comments.njk的路径,该路径是我们要传递给视图文件的数据对象(commentUser,user,commentTicket和comment),最后是回调。 该查看文件将位于emails目录中,并将用于撰写我们要发送的邮件。 传递给回调的message参数是message builder的一个实例,该实例用于通过指定我们要将邮件发送给谁,向谁发送邮件以及邮件的主题来构建邮件。

Now let's create the email view file. Create a new ticket_comments.njk file within the resources/views/email directory and add:

现在,让我们创建电子邮件视图文件。 在resources/views/email目录中创建一个新的ticket_comments.njk文件,并添加:

Suppor Ticket

{

{ comment.comment }}

---

Replied by: {

{ user.username }}

Title: {

{ commentTicket.title }}

Ticket ID: {

{ commentTicket.ticket_id }}

Status: {

{ commentTicket.status }}

You can view the ticket at any time at http://localhost:3333/tickets/{

{ commentTicket.ticket_id }}

( )

The last feature of our support ticket application is the ability to mark a ticket as closed. But a ticket can only be marked as closed by an admin. So we need to setup an admin. Remember from part 1 when we created our users table, we created a column called is_admin with a default value of 0 which indicate not an admin. A quick refresher:

支持票证应用程序的最后一个功能是能够将票证标记为已关闭。 但是票证只能由管理员标记为已关闭。 因此,我们需要设置一个管理员。 请记住,从第1部分开始,当我们创建users表时,我们创建了一个名为is_admin的列,其默认值为0,该列表示不是admin。 快速复习:

table.integer('is_admin').unsigned().default(0);

( )

We are going to create an AdminMiddleware which will allow only an admin access to an admin only area. Run the command below to create AdminMiddleware:

我们将创建一个AdminMiddleware ,它将仅允许管理员访问仅管理员区域。 运行以下命令以创建AdminMiddleware

./ace make:middleware AdminMiddleware

Update the handle() with:

使用以下命令更新handle()

// app/Http/Middleware/AdminMiddleware.js* handle (request, response, next) {
// Redirect to homepage if the currently authenticated user is not an admin if (request.currentUser.is_admin !== 1) {
response.redirect('/'); } yield next}

If the authenticated user is not an admin, he/she will be redirected to the homepage, else will proceed to the admin area. Next, we need to register our newly created middleware. Open app/Http/kernel.js and add the new middleware to the namedMiddleware array. You should have something like below after adding:

如果通过身份验证的用户不是管理员,则他/她将被重定向到主页,否则将进入管理区域。 接下来,我们需要注册我们新创建的中间件。 打开app/Http/kernel.js并将新的中间件添加到namedMiddleware数组中。 添加后,您应该具有以下内容:

// app/Http/kernel.jsconst namedMiddleware = {
... admin: 'App/Http/Middleware/AdminMiddleware'}

Now that the admin middleware has been registered, let's go on and create our admin specific routes. Add the following to app/Http/routes.js

现在已经注册了管理员中间件,让我们继续创建我们的管理员专用路由。 将以下内容添加到app/Http/routes.js

// app/Http/routes.jsRoute.group('admin', function () {
Route.get('tickets', 'TicketsController.index'); Route.post('close_ticket/:ticket_id', 'TicketsController.close');}).prefix('admin').middleware('admin')

The code above is pretty straightforward, define some routes only an admin can access. The first route /admin/tickets will trigger the index() (which we are yet to create) on the TicketsController which will get all the tickets that have been created and render a view file passed along the tickets.

上面的代码非常简单,定义了一些仅管理员可以访问的路由。 第一个路由/admin/tickets将在TicketsController上触发index() (我们尚未创建),该TicketsController将获取所有已创建的票证并呈现沿票证传递的视图文件。

// app/Http/Controllers/TicketsController.js/*** Display all tickets.*/* index(request, response) {
// Get all tickets const tickets = yield Ticket.all() // Get all categories const categories = yield Category.all() yield response.sendView('tickets.index', {
tickets: tickets.toJSON(), categories: categories.toJSON() })}

For the view file, create a file index.njk within the resources/views/tickets directory and paste the code into it:

对于视图文件,在resources/views/tickets目录中创建一个文件index.njk并将代码粘贴到其中:

{% extends 'layouts.master' %}{% block title %} All Tickets {% endblock %}{% block content %}
Tickets
{% if tickets.length == 0 %}

There are currently no tickets.

{% else %}
{% for ticket in tickets %}
{% endfor %}
Category Title Status Last Updated Actions
{% for category in categories %} {% if category.id == ticket.category_id %} { { category.name }} {% endif %} {% endfor %} #{ { ticket.ticket_id }} - { { ticket.title }} {% if ticket.status == 'Open' %} { { ticket.status }} {% else %} { { ticket.status }} {% endif %} { { ticket.updated_at }} Comment { { form.open({ url: '/admin/close_ticket/' + ticket.ticket_id, method: 'POST' }) }} { { csrfField }} { { form.button('Close', null, { class: 'btn btn-danger' }) }} { { form.close() }}
{% endif %}
{% endblock %}

Below is what an admin page will look like:

以下是管理页面的外观:

The second route close_ticket/ticket_id will trigger the close() on the ticketsController. The method will handle closing a particular ticket.

第二路线close_ticket/ticket_id将触发close()ticketsController 。 该方法将处理关闭特定票证。

// app/Http/Controllers/TicketsController.js/*** Close the specified ticket.*/* close(request, response) {
// Get the ticket with the specified ticket_id const ticket = yield Ticket.query() .where('ticket_id', request.param('ticket_id')) .firstOrFail() // Change the ticket status to closed ticket.status = 'Closed' // Persist to database yield ticket.save() // Get the user that created the ticket const ticketOwner = yield ticket.user().fetch() // send email yield Mail.send('emails.ticket_status', {
ticketOwner, ticket }, (message) => {
message.to(ticketOwner.email, ticketOwner.username) message.from('support@adonissupport.dev') message.subject(`RE: ${
ticket.title} (Ticket ID: ${
ticket.ticket_id})`) }) yield request.with({
status: 'The ticket has been closed.' }).flash() response.redirect('back')}

We get the ticket with the ticket_id passed from the route using request.param('ticket_id'), and set it status to Closed and save it. Then send an email to the owner of the ticket. And finally, display a status message.

我们使用request.param('ticket_id')获取从路线传递的具有ticket_id的票证,并将其状态设置为“ Closed并保存。 然后将电子邮件发送给票证所有者。 最后,显示状态消息。

We need one more view file; the ticket_status email view file. Go on and create ticket_status.njk and add:

我们还需要一个视图文件。 ticket_status电子邮件视图文件。 继续并创建ticket_status.njk并添加:

Suppor Ticket Status

Hello {

{ ticketOwner.username }},

Your support ticket with ID #{

{ ticket.ticket_id }} has been marked has resolved and closed.

( )

Only authenticated users can use our support ticket application. AdonisJs has us covered by providing authenticate middleware which will allow only authenticated users access to the routes in which the auth middleware is added to. Open app/Http/routes.js and update the specified routes with:

只有经过身份验证的用户才能使用我们的支持票证应用程序。 AdonisJs通过提供身份验证中间件来覆盖我们,该中间件将仅允许经过身份验证的用户访问将auth中间件添加到的路由。 打开app/Http/routes.js并使用以下命令更新指定的路由:

// app/Http/routes.jsRoute.get('new_ticket', 'TicketsController.create').middleware('auth')Route.post('new_ticket', 'TicketsController.store').middleware('auth')Route.get('tickets/:ticket_id', 'TicketsController.show').middleware('auth')Route.get('my_tickets', 'TicketsController.userTickets').middleware('auth')Route.group('admin', function () {
Route.get('tickets', 'TicketsController.index'); Route.post('close_ticket/:ticket_id', 'TicketsController.close');}).prefix('admin').middleware(['auth', 'admin'])

We add the auth middleware to some of the routes we defined earlier. This will make these routes be accessible only to authenticated users.

我们将auth中间件添加到我们先前定义的某些路由中。 这将使只有经过身份验证的用户才能访问这些路由。

Note: The admin routes have two middlewares: auth and admin (we created earlier) which means not only an authenticated user can access these routes but must also be an admin.

注意:管理路由具有两个中间件: authadmin (我们之前创建),这意味着不仅经过身份验证的用户可以访问这些路由,而且还必须是admin。

( )

Having set up our middlewares, when an unauthenticated user tries to access authenticated users only area, they will get the error below:

设置好我们的中间件之后,当未经身份验证的用户尝试访问仅经过身份验证的用户区域时,他们将得到以下错误:

Oops! That's Awkward. Yeah, I know.

糟糕! 尴尬了。 是的,我知道。

Let's give our users a nice user experience by kindly redirecting them to the login page if they are not authenticated. To do that, open app/Listeners/Http.js and add the snippet below to it just before the DEVELOPMENT REPORTER section:

如果未通过身份验证,请将其重定向到登录页面,从而为我们的用户提供良好的用户体验。 为此,请打开app/Listeners/Http.js并将下面的代码段添加到“ DEVELOPMENT REPORTER部分之前:

// app/Listeners/Http.js/*** Handle exception thrown when unable to authenticate the request*/if (error.name === 'InvalidLoginException') {
yield response.sendView('auth.login') return}

The app/Listeners/Http.js will handle errors that occurred during an HTTP request so it a nice place to catch any exception errors not caught within a controller. Back to our error, noticed from the image above that a 401 InvalidLoginException exception error was thrown. All we have to do it listen for when the error name is InvalidLoginException and then handle it gracefully by redirecting the user to the login page.

app/Listeners/Http.js将处理HTTP请求期间发生的错误,因此它是捕获控制器内未捕获的任何异常错误的好地方。 回到我们的错误,从上图看到,抛出了401 InvalidLoginException异常错误。 我们要做的就是在错误名称为InvalidLoginException时侦听该错误,然后通过将用户重定向到登录页面来InvalidLoginException处理它。

( )

To finish up with our application, let's add a kind of landing page that users will see upon visiting our application. Open app/Http/routes.js and add the line below to it:

为了完成我们的应用程序,让我们添加一种用户访问我们的应用程序时将看到的登录页面。 打开app/Http/routes.js并在其下面添加以下行:

// app/Http/routes.jsRoute.on('/').render('home')

AdonisJs has a render() for displaying static pages. The route above will render a home view which we'll create shortly.

AdonisJs有一个render()用于显示静态页面。 上面的路线将呈现一个我们不久将创建的home视图。

Create a new file named home.njk within the resources/views and add the code below to it:

resources/views创建一个名为home.njk的新文件,并将以下代码添加到其中:

// resources/views/home.njk{% extends 'layouts.master' %}{% block title %} Welcome {% endblock %}{% block content %}

Welcome!

{% if currentUser.is_admin %}

See all tickets

{% else %}

See all your tickets or open new ticket

{% endif %}
{% endblock %}

Now when we visit the homepage of our application, we will get a screen similar as below:

现在,当我们访问应用程序的主页时,将得到类似以下的屏幕:

Below is an image of the final output of what we have built.

下面是我们构建的最终输出的图像。

( )

That's it. Our support ticket application is ready. In this tutorial, we have been able to see how easy and straightforward it is to build applications with AdonisJs. We have been able to utilize AdonisJs Query Builder to define our table structures without writing a single SQL command, layout our views with its built-in view engine without doing extra setup as with other Node.JS frameworks (Express, Hapi.js etc). We also saw Lucid ORM in action which makes it seamless to interact with our database irrelevant of the database type. Lastly, we saw Ace, a powerful interactive shell which we used to scaffold and perform some operations from within a terminal. Though we didn't touch all of the great features that AdonisJs provides out of the box. In subsequent tutorials, we'll be looking more at AdonisJs and how to do great stuff with it.

而已。 我们的支持票申请已准备就绪。 在本教程中,我们已经看到使用AdonisJs构建应用程序是多么容易和直接。 我们已经能够利用AdonisJs查询生成器来定义我们的表结构,而无需编写任何SQL命令,使用其内置的视图引擎来布局视图,而无需像其他Node.JS框架(Express,Hapi.js等)那样进行额外的设置。 。 我们还看到了Lucid ORM的实际应用,它使与数据库类型无关的数据库无缝交互成为可能。 最后,我们看到了Ace,它是一个功能强大的交互式外壳,用于从终端内部进行支架和执行一些操作。 尽管我们并未直接使用AdonisJs提供的所有出色功能。 在随后的教程中,我们将更多地研究AdonisJs以及如何用它做很多事情。

You can check out the project repository to view the complete source code. If you have any questions about the tutorial, let me know in the comments below.

您可以检出项目存储库以查看完整的源代码。 如果您对本教程有任何疑问,请在下面的评论中告诉我。

翻译自:

票务小程序源码

转载地址:http://neuwd.baihongyu.com/

你可能感兴趣的文章
@ServletComponentScan ,@ComponentScan,@Configuration 解析
查看>>
unity3d 射弹基础案例代码分析
查看>>
thinksns 分页数据
查看>>
os模块
查看>>
LINQ to SQL vs. NHibernate
查看>>
基于Angular5和WebAPI的增删改查(一)
查看>>
windows 10 & Office 2016 安装
查看>>
最短路径(SP)问题相关算法与模板
查看>>
js算法之最常用的排序
查看>>
Python——交互式图形编程
查看>>
经典排序——希尔排序
查看>>
团队编程项目作业2-团队编程项目代码设计规范
查看>>
英特尔公司将停止910GL、915GL和915PL芯片组的生产
查看>>
团队编程项目作业2-团队编程项目开发环境搭建过程
查看>>
<Using parquet with impala>
查看>>
07-Java 中的IO操作
查看>>
通过镜像下载Android系统源码
查看>>
Maven配置
查看>>
HttpServletRequest /HttpServletResponse
查看>>
SAM4E单片机之旅——24、使用DSP库求向量数量积
查看>>